#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <pthread.h>

#define handlle_error(cmd,result){  \
    if (result < 0)                 \
    {                               \
        perror(cmd);                \
        return -1;                  \
    }                               \
}   

void * read_thread(void * arg){
    // 将客户端发送的消息读取打印到控制台
    int fd = *(int *)arg;
    char *buf;
    ssize_t count ;
    buf = malloc(1024);
    while ((count = recv(fd,buf,1024,0)) > 0)
    {
        printf("接收到客户端发送的数据 %s",buf);
    }
    if (count < 0)
    {
        perror("recv");
    }      
    free(buf);
}
void * write_thread(void * arg){
    int fd = *(int *)arg;
    char *buf;
    ssize_t count ;
    buf = malloc(1024);
    while (fgets(buf,1024,stdin) != NULL)
    {   
        printf("服务端向客户端发送了一条数据\n");
        send(fd,buf,1024,0);
    }
    printf("服务端关闭写操作  挥手\n");
    free(buf);
    shutdown(fd,SHUT_WR);
}

int main(int argc, char const *argv[])
{
    struct sockaddr_in server_addr,client_addr;
    int sock_fd,acc_fd,tmp_result,pid;
    pthread_t read_thread_t,write_thread_t;
    memset(&server_addr,0,sizeof(server_addr));
    memset(&client_addr,0,sizeof(client_addr));

    // 1.赋值
    server_addr.sin_family = AF_INET;
    inet_pton(AF_INET,"192.168.10.150",&server_addr.sin_addr);
    server_addr.sin_port = htons(6666);

    // 2.创建socker
    sock_fd = socket(AF_INET,SOCK_STREAM,0);
    handlle_error("socket",sock_fd);

    // 3. 绑定地址
    tmp_result = bind(sock_fd,(struct sockaddr *)&server_addr,sizeof(server_addr));
    handlle_error("bind",tmp_result);

    // 4. 开启监听
    listen(sock_fd,1024);

    // 5. 获取客户端连接的套接子
    socklen_t size = sizeof(client_addr);
    acc_fd = accept(sock_fd,(struct sockaddr *)&client_addr,&size);
    handlle_error("accept",acc_fd);
    printf("服务端 %s:%d接收到客户端%s:%d的连接\n",inet_ntoa(server_addr.sin_addr),ntohs(server_addr.sin_port),inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port));

    // 创建读线程
    pthread_create(&read_thread_t,NULL,read_thread,&acc_fd);
    // 创建写线程
    pthread_create(&write_thread_t,NULL,write_thread,&acc_fd);

    // 挂起等待子线程运行完成
    pthread_join(read_thread_t,NULL);
    pthread_join(write_thread_t,NULL);

    return 0;
}
